
export module Tools {

    /**计算二点间的角度 */
    export function calculateAngle(startPos: { x: number, y: number }, endPos: { x: number, y: number }) {
        let vx = endPos.x - startPos.x;
        let vy = endPos.y - startPos.y;
        let normalMoveVec2 = this.normalizeVec2(vx, vy);
        let effectV = { x: 0, y: -1 }; //特效的向量
        let dotProduct = normalMoveVec2.x * effectV.x + normalMoveVec2.y * effectV.y; //点积
        let angle = Math.acos(dotProduct);
        angle = (angle * 180) / Math.PI;
        if (endPos.x < startPos.x) {
            angle = -angle;
        }
        return angle;
    }

    /**取小数点后n位 */
    export function getDotN(num: number, n: number): number {
        let s = num.toString();
        let result = s.substring(0, s.indexOf(".") + n + 1);

        return Number(result);
    }


    /**将数据转为文件下载 */
    export function downloadFile(file: File) {
        /*
          把文件转成url
           createObjectURL()参数可以传blob或者file
         */
        let url = URL.createObjectURL(file)
        let a = document.createElement("a")
        /*
        a.innerHTML = "下载文件"
        或者 a.innerText = "下载文件"
        该属性可有可无，如果页面需要显示a标签，则保留属性；
        反之则无需保留该属性
         */
        // a.innerHTML = "下载文件"
        a.style.display = "none"
        a.href = url
        /*
        这个属性为关键属性,如果不添加download属性，
        则会直接在浏览器打开该文件，对于浏览器不能打
        开的文件会显示乱码，比如压缩包
         */
        a.download = file.name
        document.body.appendChild(a)

        //为a标签赋予点击事件并点击，如果是手动点击，则无需赋予事件
        let evt = document.createEvent("MouseEvents");
        evt.initEvent("click", true, true);
        a.dispatchEvent(evt);

        //下载完成之后删除a标签
        document.body.removeChild(a);
    }

    export function buildShareId(): string {
        let share_id: string;
        var d = new Date();
        var year = d.getFullYear();
        var month = change(d.getMonth() + 1);
        var day = change(d.getDate());
        var hour = change(d.getHours());
        var minute = change(d.getMinutes());
        var second = change(d.getSeconds());
        function change(t) {
            if (t < 10) {
                return "0" + t;

            } else {
                return t;
            }
        }
        let timestr = year + month + day + hour + minute + second;
        // console.log(timestr);
        let random = Tools.limitInteger(0, 99999999);
        share_id = timestr + random;
        //console.log(random);
        return share_id;
    }

    export function checkisRepeatInArray(arr: number[]) {
        let result: boolean = false;
        for (let i = 0; i < arr.length; i++) {
            let before = arr[i];
            for (let j = i + 1; j < arr.length; j++) {
                let behind = arr[j];
                if (before === behind) {
                    return true;
                }
            }
        }
        return result;
    }

    export function formatDate() { //author: meizz   
        var d = new Date();
        var year = d.getFullYear();
        var month = change(d.getMonth() + 1);
        var day = change(d.getDate());
        var hour = change(d.getHours());
        var minute = change(d.getMinutes());
        var second = change(d.getSeconds());
        var milisecond = (d.getMilliseconds()) % 1000;
        function change(t) {
            if (t < 10) {
                return "0" + t;
            } else {
                return t;
            }
        }
        var time = year + '年-' + month + '月-' + day + '日-' + hour + '时-' + minute + '分-' + second + '秒-' + milisecond + '毫秒';
        var time2 = hour + '时-' + minute + '分-' + second + '秒-' + milisecond + '毫秒';
        return time2;
    }

    export function formatDate2(d: Date) { //author: meizz   
        var year = d.getFullYear();
        var month = change(d.getMonth() + 1);
        var day = change(d.getDate());
        var hour = change(d.getHours());
        var minute = change(d.getMinutes());
        var second = change(d.getSeconds());
        var milisecond = (d.getMilliseconds()) % 1000;
        function change(t) {
            if (t < 10) {
                return "0" + t;
            } else {
                return t;
            }
        }

        var time2 = year + '年-' + month + '月-' + day + '日-' + hour + '时-' + minute + '分-' + second + '秒-' + milisecond + '毫秒';
        // var time2 = hour + '时-' + minute + '分-' + second + '秒-' + milisecond + '毫秒';
        // var time2 = hour + ':' + minute + ':' + second;
        return time2;
    }

    /*
    ** 时间戳转换成指定格式日期
    ** eg. 
    ** dateFormat(11111111111111, 'Y年m月d日 H时i分')
    ** → "2322年02月06日 03时45分"
    */
    export function dateFormat(timestamp, formats = "Y年m月d日 H:i:s:o") {
        // formats格式包括
        // 1. Y-m-d
        // 2. Y-m-d H:i:s
        // 3. Y年m月d日
        // 4. Y年m月d日 H时i分
        formats = formats || 'Y-m-d';

        var zero = function (value) {
            if (value < 10) {
                return '0' + value;
            }
            return value;
        };

        var myDate = timestamp ? new Date(timestamp) : new Date();

        var year = myDate.getFullYear();
        var month = zero(myDate.getMonth() + 1);
        var day = zero(myDate.getDate());

        var hour = zero(myDate.getHours());
        var minite = zero(myDate.getMinutes());
        var second = zero(myDate.getSeconds());
        var ms = zero(myDate.getMilliseconds())


        return formats.replace(/Y|m|d|H|i|s|o/ig, function (matches) {
            return ({
                Y: year,
                m: month,
                d: day,
                H: hour,
                i: minite,
                s: second,
                o: ms
            })[matches];
        });
    };



    export function sortarr(arr) {
        for (let i = 0; i < arr.length - 1; i++) {
            for (let j = 0; j < arr.length - 1 - i; j++) {
                if (arr[j] > arr[j + 1]) {
                    var temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }
        return arr;
    }

    export function parseAribaToRoma(num: number) {

        let result = null;
        switch (num) {
            case 1:
                result = "Ⅰ";
                break;
            case 2:
                result = "Ⅱ";
                break;
            case 3:
                result = "iii";
                break;
            case 4:
                result = "Ⅳ";
                break;
            case 5:
                result = "Ⅴ";
                break;
            case 6:
                result = "Ⅵ";
                break;
            case 7:
                result = "Ⅶ";
                break;
            case 8:
                result = "Ⅷ";
                break;
            case 9:
                result = "Ⅸ";
                break;
        }

        return result;
    }

    export function findSameNumInArray(arr: number[]) {
        let sameNum = [];
        for (let i = 0; i < arr.length; i++) {
            let beforeNum = arr[i];
            let count = 0;
            for (let j = i + 1; j < arr.length; j++) {
                let behindNum = arr[j];

                if (beforeNum === behindNum) {
                    count++;
                    // console.log(beforeNum, behindNum, count)
                }
            }
            if (count === 2) {
                sameNum.push(beforeNum);
            }
        }
        return sameNum;
    }


    //二分查找
    export function binary_search(array: number[], item: number): number {
        let index: number;

        let low = 0;
        let high = array.length - 1;
        while (low <= high) {
            let mid = Math.floor((high + low) / 2);
            let midValue = array[mid];
            if (midValue === item) {
                return mid;
            } else if (midValue > item) {
                high = mid - 1;
            } else if (midValue < item) {
                low = mid + 1;
            }

        }

        return -1;
    }





    /**
    * 获取一个区间的随机数(带小数)
    * @param $from 最小值
    * @param $end 最大值
    * @returns {number}
    */
    export function limit($from: number, $end: number): number {
        $from = Math.min($from, $end);
        $end = Math.max($from, $end);
        var range: number = $end - $from;
        return $from + Math.random() * range;
    }

    /**
     * 获取一个区间的随机数(整数)
     * @param $from 最小值
     * @param $end 最大值
     * @returns {number}
     */
    export function limitInteger($from: number, $end: number): number {
        return Math.round(this.limit($from, $end));
    }

    /**
     * 获取一定范围内n个随机整数
     * @param start 起始值
     * @param end  终止值
     * @param n 取几个
     */
    export function getRandomNumber(start: number, end: number, n: number): number[] {
        var arr = [] as number[];
        for (var i = 0; i < n; i++) {
            var number = Math.floor(Math.random() * (end - start + 1) + start);
            if (arr.indexOf(number) < 0) {
                arr.push(number);
            } else {
                i--;
            }
        }
        return arr;
    }


    /**
     * 在一个数组中随机获取一个元素
     * @param arr 数组
     * @returns {any} 随机出来的结果
     */
    export function randomArray(arr: Array<any>): any {
        var index: number = Math.floor(Math.random() * arr.length);
        return arr[index];
    }



    /**通用对象克隆 */
    export function clone(obj) {
        let temp = null;
        if (obj instanceof Array) {
            temp = obj.concat();
        } else if (obj instanceof Function) {
            //函数是共享的是无所谓的，js也没有什么办法可以在定义后再修改函数内容
            temp = obj;
        } else {
            temp = new Object();
            for (let item in obj) {
                let val = obj[item];
                temp[item] = typeof val == 'object' ? clone(val) : val; //这里也没有判断是否为函数，因为对于函数，我们将它和一般值一样处理
            }
        }
        return temp;
    }

    export function deepCopy(obj) {
        if (typeof obj != 'object') {
            return obj;
        }
        var newobj = {};
        for (var attr in obj) {
            newobj[attr] = deepCopy(obj[attr]);
        }
        return newobj;
    }

    export function deepCopyArray(obj: Array<any>): Array<any> {
        // let res: any = [];
        // for (let i = 0; i < obj.length; i++) {
        // 	res[i] = obj[i];
        // }
        let res = [...obj];
        return res;
    }
    //解析时间
    export function parseTime(currentCount: number, type: number = 1) {
        let str, hour, minute, scond;
        if (Math.floor(currentCount / 3600) < 10) {
            hour = "0" + Math.floor(currentCount / 3600)
        } else {
            hour = "" + Math.floor(currentCount / 3600)
        }
        if (Math.floor(currentCount / 60) < 10) {
            minute = "0" + Math.floor(currentCount / 60)
        } else {
            minute = "" + Math.floor((currentCount % 3600) / 60)
        }

        if (currentCount % 60 < 10) {
            scond = "0" + currentCount % 60;
        } else {
            scond = "" + currentCount % 60;
        }

        switch (type) {
            case 1:
                str = minute + ":" + scond;
                break;
            case 2:
                str = hour + ":" + minute + ":" + scond;
                break;
        }
        return str;
    }









    export function urlEncode(param, key, encode): string {
        if (param == null) return '';
        var paramStr: string = '';
        var t = typeof (param);
        if (t == 'string' || t == 'number' || t == 'boolean') {
            paramStr += '&' + key + '=' + ((encode == null || encode) ? encodeURIComponent(param) : param);
        } else {
            for (var i in param) {
                var k = key == null ? i : key + (param instanceof Array ? '[' + i + ']' : '.' + i);
                paramStr += this.urlEncode(param[i], k, encode);
            }
        }
        return paramStr;
    }

    export function is_iPad() {
        var ua = navigator.userAgent.toLowerCase();
        if (ua.match(/iPad/i)) {
            return true;
        } else {
            return false;
        }
    }


    export function madeMd5(str: string) {
        //	return new md5().hex_md5(str);
    }
    /**
     * 是否是质数
     */
    export function isPrime(number) {
        if (typeof number !== 'number' || number < 2) {
            // 不是数字或者数字小于2
            return false;
        }

        if (number === 2) {//2是质数
            return true;
        } else if (number % 2 === 0) {//排除偶数
            return false;
        }
        var squareRoot = Math.sqrt(number);

        //因为2已经验证过，所以从3开始；且已经排除偶数，所以每次加2
        for (var i = 3; i <= squareRoot; i += 2) {
            if (number % i === 0) {
                return false;
            }
        }
        return true;
    }


    export function findLargestInArray(arr: Array<number>): Array<number> {
        arr.sort(Tools.sortNumber);
        return arr.slice(arr.length - 1);
    }

    export function sortNumber(a, b) {
        return a - b
    }



    /**
     * 自定义字符串替换
    */
    export function replaceString(value: string) {

    }




    export function unique(array: Array<any>) {
        var arr = array, i, j, len = arr.length;
        for (i = 0; i < len; i++) {
            for (j = i + 1; j < len; j++) {
                if (arr[i].text == arr[j].text) {
                    arr.splice(j, 1);
                    len--;
                    j--;
                }
            }
        }
        return arr;
    }

    /**字符串四则运算 */
    export function calculateStr(expression) {
        var priority = {
            '*': 2,
            '/': 2,
            '+': 1,
            '-': 1
        };
        var strExpression2arrExpression = function (expression) {//字符串转换为数组
            var arr = [];
            for (var i = 0, s, t, l = expression.length; i < l; i++) {
                s = expression.charAt(i);
                if (isNaN(s) && s != '.') {
                    arr.push(s);
                } else {
                    t = s;
                    while (i < l) {
                        s = expression.charAt(i + 1);
                        if (!isNaN(s) || s == '.') {
                            t += s;
                            i++;
                        } else {
                            break;
                        }
                    }
                    arr.push(parseFloat(t));
                }
            }
            return arr;
        };
        var infixExpression2prefixExpression = (function () { //将中缀表达式转换为前缀表达式
            var s1 = [], s2 = [], operator = function (o) {
                var last = s1[s1.length - 1];
                if (s1.length == 0 || last == ')') {
                    s1.push(o);
                } else if (priority[o] >= priority[last]) {
                    s1.push(o);
                } else {
                    s2.push(s1.pop());
                    operator(o);
                }
            };
            return function (arrExpression) {
                s1.length = 0;
                s2.length = 0;
                for (var i = arrExpression.length - 1, o; i >= 0; i--) {
                    o = arrExpression[i]
                    if (!isNaN(o)) {
                        s2.push(o);
                    } else {
                        if (o == '+' || o == '-' || o == '*' || o == '/') {//运算符
                            operator(o)
                        } else {//括号
                            if (o == ')') {//右括号
                                s1.push(o)
                            } else {//左括号
                                var s = s1.pop();
                                while (s != ')') {
                                    s2.push(s);
                                    s = s1.pop();
                                }
                            }
                        }
                    }
                }
                if (s1.length > 0) {
                    while (s1[0] != undefined) {
                        s2.push(s1.pop())
                    }
                }
                s1.length = 0;
                return s2.slice();
            }
        })();
        var computePrefixExpression = (function () {
            var s1 = [], result;
            return function (prefixExpression) {
                s1.length = 0;
                //计算
                while (prefixExpression.length > 0) {
                    var o = prefixExpression.shift();
                    if (!isNaN(o)) {
                        s1.push(o);
                    } else {
                        switch (o) {
                            case '+':
                                {
                                    result = s1.pop() + s1.pop();
                                    break;
                                }
                            case '-':
                                {
                                    result = s1.pop() - s1.pop();
                                    break;
                                }
                            case '*':
                                {
                                    result = s1.pop() * s1.pop();
                                    break;
                                }
                            case '/':
                                {
                                    result = s1.pop() / s1.pop();
                                    break;
                                }
                        }
                        s1.push(result);
                    }
                    //console.log(s2,s1)
                }
                //console.log(s1)
                return s1[0];
            }
        })();

        return (infixExpression2prefixExpression(strExpression2arrExpression(expression)));
    }




    function replaceSpecial(replaceArr: any[], value: string) {
        for (let i = 0; i < replaceArr.length; i++) {
            let k = replaceArr[i][0];
            let v = replaceArr[i][1];
            value = value.replace(k, v);
        }
        return value;
    };



    function getSpace(count: number): string {
        let space = "";
        for (let index = 0; index < count; index++) {
            space += "\t";
        }
        return space;
    }


    /**
     * 获取以时间戳为标准的 设定的时间戳  
     * @param timeStamp 一般以当前的时间戳  也可以自己定一个时间戳
     * @param setTime 20:00:00 
     */
    export function getSetTimeStamp(timeStamp: number, setTime: string): number {

        let timeData = setTime.split(":");

        let now = new Date(timeStamp);
        now.setHours(Number(timeData[0]));
        now.setMinutes(Number(timeData[1]));
        now.setSeconds(Number(timeData[2]));

        return Date.parse(now.toString());
    }


    /**根据数字获取汉字*/
    export function changeToCN(num: number): string {
        return num.toString();
        let words = ["零", "一", "二", "三", "四", "五", "六", "七", "八", "九", "十"];
        let adds = ["", '十', '百', '千', '万', '亿', '十', '百', '千'];
        if (words[num]) {
            return words[num];
        }
        else if (num > 10 && num < 20) {
            let numStr = num.toString();
            let n = numStr.substring(1, 2);
            let result = adds[1] + words[n];
            return result;
        }
        else if (num > 10) {
            let result = "";
            let numStr = num.toString();
            for (var i = 0; i < numStr.length; ++i) {
                let n = numStr.substring(i, i + 1);
                let m = numStr.length - i - 1;
                result += words[n] + adds[m];
            }
            return result;
        }
        else return "零";
    }

    export function IntToUint8Array(num: number, Bits: number): number[] {
        let resArry = [];
        let xresArry = [];
        let binaryStr: string = num.toString(2);
        for (let i = 0; i < binaryStr.length; i++)
            resArry.push(parseInt(binaryStr[i]));

        if (Bits) {
            for (let r = resArry.length; r < Bits; r++) {
                resArry.unshift(0);
            }
        }

        let resArryStr = resArry.join("");
        for (let j = 0; j < Bits; j += 8)
            xresArry.push(parseInt(resArryStr.slice(j, j + 8), 2));
        return xresArry;
    }


    export function Uint8ArrayToInt(uint8Ary: Uint8Array, len: number) {
        let retInt: number = 0;
        for (let i = 0; i < len; i++) {
            retInt |= (uint8Ary[i] << (8 * (len - i - 1)));
        }
        return retInt;
    }



}